<?php


namespace App\Common\Services;

use App\BaseService;
use App\Common\Models\Sms;
use Illuminate\Support\Facades\DB;

/**
 * Class SmsService
 * @package App\Common\Services
 */
class SmsService extends BaseService
{

    // 万能验证码白名单
    protected $white_list = [
        '15822623833',
        '15534053524',
        '13757117660',
        '15701048101',
        '18042008796',
        '18072814966',
        '15534053516'
    ];

    /**
     * @var array
     */
    protected $aliyun_template_code = [
        'login' => [
            'code' => 'SMS_215485039',
            'template' => '验证码：%s，您正在登录，若非本人操作，请勿泄露。'
        ],
        'change_phone' => [
            'code' => 'SMS_215485040',
            'template' => '验证码%s，您正在进行身份验证，打死不要告诉别人哦！'
        ],
        'verify' => [
            'code' => 'SMS_215485040',
            'template' => '验证码%s，您正在进行身份验证，打死不要告诉别人哦！'
        ]
    ];

    protected static $config = [
        'default' => [
            'aliyun' => \fendui\gateways\aliyun::class,
            'ihuyi' => \fendui\gateways\ihuyi::class
        ],
        'gateways' => [
            'aliyun' => [
                'access_key_id' => 'LTAI5t7CyUTRFfvAg2hEpK8H',
                'access_key_secret' => '4PahHZmxGW6h8hFTct2HKgGqxAFIxG',
                'sign_name' => '掌无疾',
            ],
            'ihuyi' => [
                'account' => '',
                'password' => '',
                'sign_name' => '',
            ],
        ],
    ];

    /**
     * User: zhangchaoqun
     * DateTime: 2021/6/10 6:34 下午
     * Describe: 校验验证码是否正确
     * Version: V1.0
     */
    public function verifyCode(string $phone, string $code, string $type)
    {
        if (!isset($this->aliyun_template_code[$type])) {
           throw new \Exception('短信类型不存在');
        }

        // 万能验证码
        if ($code == '112233' && in_array($phone, $this->white_list)) {
            return true;
        }

        // 比对验证码是否正确
        $codeData = Sms::where('phone', '=', $phone)
            ->where('code', '=', $code)
            ->where('type', '=', $type)
            ->orderBy('id', 'desc')
            ->first();
        if (!$codeData) {
            throw new \Exception('验证码错误');
        }

        // 大于5分钟验证码失效
        $date = date('Y-m-d H:i:s', strtotime("$codeData->created_at +5 minute"));
        if (strtotime($date) < time()) {
            throw new \Exception('验证码超时');
        }

        if ($code != $codeData->code) {
            throw new \Exception('验证码不正确');
        }
    }

    /**
     * User: zhangchaoqun
     * DateTime: 2021/6/10 6:35 下午
     * Describe: 发送短信验证码
     * Version: V1.0
     * @return \Illuminate\Http\JsonResponse
     */
    public function sendCode(string $phone, string $type)
    {
        if (!isset($this->aliyun_template_code[$type])) {
            throw new \Exception('短信类型不存在');
        }

        $code = mt_rand(100000, 999999);

        // 验证用户是否1分钟内重复发送
        $exists = Sms::where('phone', '=', $phone)
            ->where('type', '=', $type)
            ->where('created_at', '>=', date('Y-m-d H:i:s', strtotime('+1 minute')))
            ->exists();
        if ($exists) {
            throw new \Exception('1分钟内请勿重复发送');
        }

        $data = [
            'template_code' => $this->aliyun_template_code[$type]['code'],
            'code' => $code
        ];

        $resp = self::send($phone, $data);
        $gateway = !empty($resp['gateway']) ? $resp['gateway'] : 'aliyun';
        $resp = json_decode($resp['response'], true);
        $msssage = sprintf($this->aliyun_template_code[$type]['template'], $code);

        if ($resp['Code'] != 'OK') {
            throw new \Exception($resp['Message']);
        }

        $db = [
            'gateway' => $gateway,
            'phone' => $phone,
            'code' => $code,
            'type' => $type,
            'message' => $msssage,
            'data' => json_encode($data),
            'response' => json_encode($resp),
            'created_at' => date('Y-m-d H:i:s'),
            'updated_at' => date('Y-m-d H:i:s'),
        ];

        Sms::insert($db);
    }

    /**
     * @param $phone
     * @param array $data
     * @return mixed
     */
    public static function send($phone, $data = [])
    {
        $sms = new \fendui\Sms(self::$config);
        return $sms->send($phone, $data);
    }
}
